using System;
using System.Collections.Generic;
using UnityEngine.Purchasing;
using System.Security.Cryptography;

namespace UnityEngine.Purchasing.Security
{
	internal class GooglePlayValidator
	{
		private RSAKey key;
		public GooglePlayValidator (byte[] rsaKey)
		{
			key = new RSAKey (rsaKey);
		}

		public GooglePlayReceipt Validate(string receipt, string signature) {
			var rawReceipt = System.Text.Encoding.UTF8.GetBytes(receipt); // "{\"orderId\":\"G...
			var rawSignature = System.Convert.FromBase64String(signature);

			if (!key.Verify (rawReceipt, rawSignature)) {
				throw new InvalidSignatureException ();
			}

			var dic = (Dictionary<string, object>)MiniJson.JsonDecode (receipt);
			object orderID, packageName, productId, purchaseToken, purchaseTime, purchaseState;

			dic.TryGetValue ("orderId", out orderID);
			dic.TryGetValue ("packageName", out packageName);
			dic.TryGetValue ("productId", out productId);
			dic.TryGetValue ("purchaseToken", out purchaseToken);
			dic.TryGetValue ("purchaseTime", out purchaseTime);
			dic.TryGetValue ("purchaseState", out purchaseState);

			// Google specifies times in milliseconds since 1970.
			var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
			// NOTE: to safely handle null values for these fields, using Convert.ToDouble & ToInt32 in place of casts
		    var time = epoch.AddMilliseconds(Convert.ToDouble(purchaseTime));
		    var state = (GooglePurchaseState)Convert.ToInt32(purchaseState);

			return new GooglePlayReceipt ((string) productId, (string) orderID, (string) packageName,
				(string) purchaseToken, time, state);
		}
	}
}
